package com.uinnova.product.eam.service.dm.impl;

import com.alibaba.druid.DbType;
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;
import com.alibaba.druid.sql.ast.statement.SQLColumnConstraint;
import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;
import com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;
import com.alibaba.druid.sql.ast.statement.SQLNotNullConstraint;
import com.alibaba.druid.sql.parser.SQLParserFeature;
import com.alibaba.druid.util.JdbcConstants;
import com.alibaba.fastjson.JSON;
import com.binary.core.exception.BinaryException;
import com.binary.core.util.BinaryUtils;
import com.google.common.collect.Lists;
import com.uinnova.product.eam.base.exception.ServerException;
import com.uinnova.product.eam.base.util.EamUtil;
import com.uinnova.product.eam.config.Env;
import com.uinnova.product.eam.model.EamArtifactVo;
import com.uinnova.product.eam.model.bm.SavePrivateBatchCIContext;
import com.uinnova.product.eam.model.diagram.DiagramNodeJson;
import com.uinnova.product.eam.model.dm.DataModelAttribute;
import com.uinnova.product.eam.model.dm.DataModelDataType;
import com.uinnova.product.eam.model.dm.DataModelEntity;
import com.uinnova.product.eam.model.dm.bean.AttrAndCiDto;
import com.uinnova.product.eam.model.dm.bean.DataModelAttributeVo;
import com.uinnova.product.eam.model.dm.bean.DataModelEntityNodeVo;
import com.uinnova.product.eam.model.dm.bean.DataModelEntityVo;
import com.uinnova.product.eam.model.enums.ArtifactEnum;
import com.uinnova.product.eam.model.enums.DataBaseType;
import com.uinnova.product.eam.model.vo.EntityAndAttributeVo;
import com.uinnova.product.eam.service.ICISwitchSvc;
import com.uinnova.product.eam.service.IEamArtifactSvc;
import com.uinnova.product.eam.service.IEamCIClassApiSvc;
import com.uinnova.product.eam.service.dm.DataModelSqlSvc;
import com.uinnova.product.eam.service.impl.IamsCIPrivateSvc;
import com.uinnova.product.eam.service.impl.IamsCIRltSwitchSvc;
import com.uinnova.product.vmdb.comm.model.ci.CCcCi;
import com.uinnova.product.vmdb.comm.model.ci.CcCi;
import com.uinnova.product.vmdb.comm.model.ci.CcCiAttrDef;
import com.uinnova.product.vmdb.comm.model.ci.CcCiClass;
import com.uinnova.product.vmdb.provider.ci.bean.CcCiClassInfo;
import com.uinnova.product.vmdb.provider.ci.bean.CcCiInfo;
import com.uinnova.project.api.diagram.v2.client.ESDiagramApiClient;
import com.uinnova.project.base.diagram.comm.model.ESDiagram;
import com.uinnova.project.base.diagram.comm.model.ESDiagramDTO;
import com.uinnova.project.base.diagram.comm.model.ESDiagramModel;
import com.uinnova.project.base.diagram.comm.model.ESDiagramNode;
import com.uino.api.client.cmdb.IRltClassApiSvc;
import com.uino.bean.cmdb.base.ESCIClassInfo;
import com.uino.bean.cmdb.base.ESCIInfo;
import com.uino.bean.cmdb.base.LibType;
import com.uino.bean.cmdb.business.BindCiRltRequestDto;
import com.uino.dao.util.ESUtil;
import com.uino.util.sys.SysUtil;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 数据建模sql处理相关接口实现
 * @author ch
 */
@Slf4j
@Service
public class DataModelSqlSvcImpl implements DataModelSqlSvc {

    @Value("${http.resource.space}")
    private String httpResourceUrl;
    @Autowired
    private Configuration freeMarker;
    @Resource
    private ESDiagramApiClient diagramApiClient;
    @Resource
    private IEamArtifactSvc artifactSvc;
    @Resource
    private ICISwitchSvc iciSwitchSvc;
    @Resource
    private IamsCIPrivateSvc ciPrivateSvc;
    @Resource
    private IEamCIClassApiSvc ciClassApiSvc;
    @Resource
    private IamsCIRltSwitchSvc rltSwitchSvc;
    @Resource
    private IRltClassApiSvc rltClassApiSvc;
    private static final String NULL = "NULL";
    private static final String NODE_JSON = "{\"shapeName\":\"Entity\",\"category\":\"ER-entity\",\"figure\":\"RoundedRectangle\",\"width\":360,\"height\":240,\"strokeWidth\":1,\"parameter1\":4,\"stroke\":\"#DFE3E8\",\"fill\":\"#F1F3F5\",\"items\":[],\"erType\":1,\"shapeDescribe\":\"\",\"sourceLibType\":\"PRIVATE\",\"zOrder\":0,\"loc\":\"200 140\",\"isDesignLibrary\":false,\"multiText\":[]}";

    @Override
    public ResponseEntity<byte[]> exportCreateTable(String energyId, LibType libType, DataBaseType dataBase) {
        List<ESDiagramDTO> diagramList = diagramApiClient.queryFullDiagramByIds(Collections.singletonList(energyId));
        if(CollectionUtils.isEmpty(diagramList)){
            throw new ServerException("未查询到当前视图信息!");
        }
        ESDiagramDTO diagramDto = diagramList.get(0);
        //校验视图是否是物理实体图
        EamArtifactVo artifact = artifactSvc.queryArtifact(Long.parseLong(diagramDto.getDiagram().getViewType()));
        if (BinaryUtils.isEmpty(artifact)) {
            throw new ServerException("未查询到当前视图制品信息!");
        }
        if (!ArtifactEnum.PHYSICAL_ENTITY.getArtifactType().equals(artifact.getTypeClassification())) {
            throw new ServerException("当前视图不是物理实体关系图,无法导出DDL!");
        }
        List<ESDiagramModel> modelList = diagramDto.getDiagram().getModelList();
        List<DataModelEntityVo> entityTemplate = initData(modelList, diagramDto.getDiagram().getOwnerCode(), dataBase, libType);
        if (BinaryUtils.isEmpty(entityTemplate)) {
            throw new ServerException("当前视图未查询到可导出DDL实体!");
        }
        Template template;
        ResponseEntity<byte[]> resource;
        try {
            String name = "MySQL-DDL-create-table.ftl";
            if(BinaryUtils.isEmpty(dataBase)){
                dataBase = DataBaseType.MYSQL;
            } else if (DataBaseType.ORACLE.equals(dataBase)){
                name = "Oracle-DDL-create-table.ftl";
            }
            template = freeMarker.getTemplate(name);
            Map<String, List<DataModelEntityVo>> entityMap = new HashMap<>(1);
            entityMap.put("data", entityTemplate);
            String content = FreeMarkerTemplateUtils.processTemplateIntoString(template, entityMap);
            InputStream inputStream = IOUtils.toInputStream(content, StandardCharsets.UTF_8);
            ByteArrayOutputStream output = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024*4];
            int n;
            while (-1 != (n = inputStream.read(buffer))) {
                output.write(buffer, 0, n);
            }
            HttpHeaders headers = new HttpHeaders();
            byte[] bytes = output.toByteArray();
            String fileName = diagramDto.getDiagram().getName()+ "-" + dataBase + ".sql";
            headers.add("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
            resource = new ResponseEntity<>(bytes, headers, HttpStatus.OK);
        } catch (TemplateException | IOException e) {
            throw new ServerException("DDL模版格式有误!");
        } catch (Exception e) {
            throw new ServerException("DDL文件导出失败!");
        }
        return resource;
    }

    private List<DataModelEntityVo> initData(List<ESDiagramModel> modelList, String ownerCode, DataBaseType dataBase, LibType libType){
        List<DataModelEntityVo> result = new ArrayList<>();
        Map<String, List<String>> entityCodeMap = new LinkedHashMap<>(16);
        List<String> attrCodeList = new ArrayList<>();
        for (ESDiagramModel model : modelList) {
            if(BinaryUtils.isEmpty(model.getNodeDataArray())){
                continue;
            }
            for (ESDiagramNode node : model.getNodeDataArray()) {
                if(BinaryUtils.isEmpty(node.getNodeJson())){
                    continue;
                }
                DiagramNodeJson nodeJson = JSON.parseObject(node.getNodeJson(), DiagramNodeJson.class);
                if(BinaryUtils.isEmpty(nodeJson.getErType())){
                    continue;
                }
                List<String> attrCodes = new ArrayList<>();
                if(!BinaryUtils.isEmpty(nodeJson.getItems())){
                    for (DataModelEntityNodeVo item : nodeJson.getItems()) {
                        attrCodes.add(item.getCiCode());
                    }
                    attrCodeList.addAll(attrCodes);
                }
                entityCodeMap.put(nodeJson.getCiCode(), attrCodes);
            }
        }
        Map<String, ESCIInfo> entityMap;
        if(!BinaryUtils.isEmpty(entityCodeMap)){
            List<ESCIInfo> entityList = iciSwitchSvc.getCiByCodes(Lists.newArrayList(entityCodeMap.keySet()), ownerCode, libType);
            entityMap = entityList.stream().collect(Collectors.toMap(CcCi::getCiCode, each -> each, (k1, k2) -> k2));
        } else {
            return result;
        }
        Map<String, ESCIInfo> attrMap = new HashMap<>(attrCodeList.size());
        if(!BinaryUtils.isEmpty(attrCodeList)){
            List<ESCIInfo> attrList = iciSwitchSvc.getCiByCodes(attrCodeList, ownerCode, libType);
            attrMap = attrList.stream().collect(Collectors.toMap(CcCi::getCiCode, each -> each, (k1, k2) -> k2));
        }
        //获取数据类型映射
        Map<String, String> dataTypeMap = getDataTypeMap(dataBase.toString());
        for (Map.Entry<String, List<String>> each : entityCodeMap.entrySet()) {
            ESCIInfo entity = entityMap.get(each.getKey());
            if(BinaryUtils.isEmpty(entity)){
                continue;
            }
            DataModelEntityVo entityVo = new DataModelEntityVo(entity);
            Set<String> filterName = new HashSet<>();
            for (String code : each.getValue()) {
                ESCIInfo attr = attrMap.get(code);
                if(BinaryUtils.isEmpty(attr)){
                    continue;
                }
                Object enName = attr.getAttrs().get(DataModelAttribute.NAME_EN);
                if(!BinaryUtils.isEmpty(enName)){
                    if(filterName.contains(enName.toString())){
                        throw new ServerException("【"+entityVo.getName()+"】中实体属性的英文名重复，请调整!");
                    }else{
                        filterName.add(enName.toString());
                    }
                }
                DataModelAttributeVo attributeVo = new DataModelAttributeVo(entityVo.getName(), attr, dataTypeMap);
                if(attributeVo.getPk()){
                    entityVo.getPkList().add(attributeVo.getName());
                }
                entityVo.getAttrList().add(attributeVo);
            }
            result.add(entityVo);
        }
        return result;
    }

    /**
     * 获取数据类型与对应数据库的映射值
     * @param dataBase 数据库类型
     * @return 自定义类型与各数据库类型映射map
     */
    private Map<String, String> getDataTypeMap(String dataBase){
        Long domainId = SysUtil.getCurrentUserInfo().getDomainId();
        CcCiClassInfo dataTypeClass = ciClassApiSvc.getCIClassByCodes(Env.DATA_TYPE.getCode());
        CCcCi ccCi = new CCcCi();
        ccCi.setClassId(dataTypeClass.getCiClass().getId());
        List<CcCiInfo> dataTypeList = iciSwitchSvc.queryCiInfoList(domainId, ccCi, null, true, false, LibType.DESIGN);
        if(BinaryUtils.isEmpty(dataTypeList)){
            return Collections.emptyMap();
        }
        Map<String, String> result = new HashMap<>(dataTypeList.size());
        for (CcCiInfo each : dataTypeList) {
            String type = each.getAttrs().get(DataModelDataType.NAME_CN);
            String dataBaseType = each.getAttrs().get(dataBase);
            if(BinaryUtils.isEmpty(dataBaseType)){
                continue;
            }
            result.put(type, dataBaseType);
        }
        return result;
    }

    @Override
    public AttrAndCiDto importDDL(MultipartFile multipartFile, String diagramId, DataBaseType dataBase) {
        ESDiagram diagram = diagramApiClient.getEsDiagram(diagramId, 0);
        String classCode = checkDiagramType(diagram);
        String ddl;
        try {
            byte[] ddlBytes = multipartFile.getBytes();
            ddl = new String(ddlBytes, StandardCharsets.UTF_8);
        } catch (IOException e) {
            throw new RuntimeException("解析文件内容失败!");
        }
        List<SQLStatement> statements;
        try {
            DbType dbType = JdbcConstants.MYSQL;
            if(DataBaseType.ORACLE.equals(dataBase)){
                dbType = JdbcConstants.ORACLE;
            }
            statements = SQLUtils.parseStatements(ddl, dbType, SQLParserFeature.KeepComments);
        } catch (Exception e) {
            throw new RuntimeException("解析文件内容失败,文件格式有误!");
        }
        ESCIClassInfo entityClass = ciClassApiSvc.getCIClassByCode(classCode);
        Long entityClassId = entityClass.getId();
        CcCiClassInfo attrClass = ciClassApiSvc.getCIClassByCodes(Env.ATTRIBUTES.getCode());
        Long attrClassId = attrClass.getCiClass().getId();
        String ownerCode = diagram.getOwnerCode();
        CcCiClassInfo rltClass = rltClassApiSvc.getRltClassByName(SysUtil.getCurrentUserInfo().getDomainId(), Env.DM_INCLUDE);
        if(BinaryUtils.isEmpty(rltClass)){
            throw new ServerException("关系分类" + Env.DM_INCLUDE + "不存在!");
        }
        Long rltClassId = rltClass.getCiClass().getId();
        //批量绑定关系
        List<BindCiRltRequestDto> bindList = new ArrayList<>();
        Map<String, ESCIInfo> entityMap = new HashMap<>();
        Map<String, SQLCreateTableStatement> entityNameMap = new HashMap<>();
        List<ESCIInfo> entityList = new ArrayList<>();
        //实体去重
        Set<String> entityFilter = new HashSet<>();
        for (SQLStatement statement : statements) {
            if (!(statement instanceof SQLCreateTableStatement)) {
                continue;
            }
            SQLCreateTableStatement createTableStatement = (SQLCreateTableStatement) statement;
            ESCIInfo ciInfo = getNewEntity(createTableStatement, entityClassId, ownerCode);
            String name = ciInfo.getAttrs().get(DataModelEntity.NAME_CN).toString();
            if(entityFilter.add(name)){
                entityNameMap.put(name, createTableStatement);
                entityList.add(ciInfo);
            }
        }
        Map<String, SavePrivateBatchCIContext> entityContext = ciPrivateSvc.saveOrUpdateBatchCI(entityList, Collections.singletonList(entityClassId), ownerCode, ownerCode);
        List<ESCIInfo> attrList = new ArrayList<>();
        //实体属性去重
        Set<String> attrFilter = new HashSet<>();
        for (Map.Entry<String, SavePrivateBatchCIContext> entry : entityContext.entrySet()) {
            ESCIInfo entity = entry.getValue().getEsCi();
            String name = entity.getAttrs().get(DataModelEntity.NAME_CN).toString();
            SQLCreateTableStatement createTableStatement = entityNameMap.get(name);
            entityMap.put(entity.getCiCode(), entity);
            List<String> primaryKeyNames = createTableStatement.getPrimaryKeyNames();
            for (SQLColumnDefinition each : createTableStatement.getColumnDefinitions()) {
                ESCIInfo attribute = getNewAttribute(each, primaryKeyNames, entity.getCiCode(), attrClassId, ownerCode);
                String attrName = attribute.getAttrs().get(DataModelAttribute.NAME_CN).toString();
                if(attrFilter.add(entity.getCiCode() + "-" + attrName)){
                    attrList.add(attribute);
                }
            }
        }
        Map<String, SavePrivateBatchCIContext> context = ciPrivateSvc.saveOrUpdateBatchCI(attrList, Collections.singletonList(attrClassId), ownerCode, ownerCode);
        Map<String, List<ESCIInfo>> entityAttrMap = new HashMap<>();
        for (Map.Entry<String, SavePrivateBatchCIContext> each : context.entrySet()) {
            String entityCode = each.getValue().getAttrsStr().get(DataModelAttribute.ENTITY);
            if(entityCode == null){
                continue;
            }
            ESCIInfo entity = entityMap.get(entityCode);
            if(entity == null){
                continue;
            }
            ESCIInfo attrCiInfo = each.getValue().getEsCi();
            BindCiRltRequestDto bindRlt = BindCiRltRequestDto.builder().ownerCode(ownerCode).repetitionError(false).rltClassId(rltClassId)
                    .custom1("3").sourceCiId(entity.getId()).targetCiId(attrCiInfo.getId()).build();
            bindList.add(bindRlt);
            attrCiInfo.setShape(attrClass.getCiClass().getShape());
            entityAttrMap.computeIfAbsent(entityCode, key -> new ArrayList<>()).add(attrCiInfo);
        }
        rltSwitchSvc.bindCiRltBatch(bindList, LibType.PRIVATE);
        List<EntityAndAttributeVo> entityAttrResult = new ArrayList<>();
        for (Map.Entry<String, List<ESCIInfo>> entry : entityAttrMap.entrySet()) {
            ESCIInfo entity = entityMap.get(entry.getKey());
            if(entity == null){
                continue;
            }
            entity.setShape(entityClass.getShape());
            EntityAndAttributeVo vo = new EntityAndAttributeVo(entity, entry.getValue());
            entityAttrResult.add(vo);
        }
        AttrAndCiDto result = new AttrAndCiDto();
        result.setEntityAndAttributeVos(entityAttrResult);
        result.setCount(entityMap.size());
        result.setEntityAttrDefs(EamUtil.copy(entityClass.getAttrDefs(), CcCiAttrDef.class));
        result.setAttrAttrDefs(attrClass.getAttrDefs());
        return result;
    }

    /**
     * 校验视图制品类型,返回实体code
     * @param diagram 视图
     * @return 实体code
     */
    private String checkDiagramType(ESDiagram diagram) {
        if(diagram == null){
            throw new RuntimeException("未查询到当前视图!");
        }
        String artifactId = diagram.getViewType();
        if(BinaryUtils.isEmpty(artifactId)){
            throw new RuntimeException("无法在自由视图导入DDL!");
        }
        EamArtifactVo artifact = artifactSvc.queryArtifact(Long.valueOf(artifactId));
        if(BinaryUtils.isEmpty(artifact)){
            throw new RuntimeException("未获取到当前视图绑定的制品信息,无法在自由视图导入DDL!");
        }
        Integer type = artifact.getTypeClassification();
        String classCode;
        if (ArtifactEnum.CONCEPTUAL_ENTITY.getArtifactType().equals(type)) {
            classCode = Env.CONCEPTION_ENTITY.getCode();
        } else if (ArtifactEnum.RELATION_ENTITY.getArtifactType().equals(type) || ArtifactEnum.SYS_LOGICAL_ENTITY.getArtifactType().equals(type)) {
            classCode = Env.LOGIC_ENTITY.getCode();
        } else if (ArtifactEnum.PHYSICAL_ENTITY.getArtifactType().equals(type)) {
            classCode = Env.PHYSICAL_ENTITY.getCode();
        } else {
            throw new BinaryException("当前视图绑定的制品类型非er图制品类型，请检查");
        }
        return classCode;
    }

    /**
     * 根据ddl解析对象创建实体对象
     * @param statement ddl
     * @param classId 实体分类id
     * @param loginCode 用户
     * @return 实体
     */
    private ESCIInfo getNewEntity(SQLCreateTableStatement statement, Long classId, String loginCode){
        ESCIInfo entity = new ESCIInfo();
        entity.setClassId(classId);
        entity.setOwnerCode(loginCode);
        entity.setCiCode(String.valueOf(ESUtil.getUUID()));
        String enName = statement.getTableName().replaceAll("[`']", "");
        String cnName = enName;
        if(statement.getComment() != null){
            String comment = statement.getComment().toString().replaceAll("[`']", "");
            if(comment.codePointCount(0, comment.length()) < 60){
                cnName = comment;
            }
        }
        Map<String, Object> attrs = new HashMap<>();
        attrs.put(DataModelEntity.NAME_CN, cnName);
        attrs.put(DataModelEntity.NAME_EN, enName);
        entity.setAttrs(attrs);
        return entity;
    }

    /**
     * 根据ddl对象解析为实体属性对象
     * @param column ddl对象
     * @param primaryKeyNames 主键名称集合
     * @param classId 实体属性分类id
     * @param loginCode 用户
     * @return 实体属性ci
     */
    private ESCIInfo getNewAttribute(SQLColumnDefinition column, List<String> primaryKeyNames, String entityCode, Long classId, String loginCode){
        ESCIInfo attribute = new ESCIInfo();
        attribute.setClassId(classId);
        attribute.setOwnerCode(loginCode);
        attribute.setCiCode(String.valueOf(ESUtil.getUUID()));
        String enName = column.getNameAsString().replaceAll("[`']", "");
        String cnName = enName;
        if(column.getComment() != null){
            String comment = column.getComment().toString().replaceAll("[`']", "");
            if(comment.codePointCount(0, comment.length()) < 60){
                cnName = comment;
            }
        }
        Map<String, Object> attrs = new HashMap<>();
        attrs.put(DataModelAttribute.NAME_CN, cnName);
        attrs.put(DataModelAttribute.NAME_EN, enName);
        if(column.getDataType() != null){
            attrs.put(DataModelAttribute.DATA_TYPE, column.getDataType().toString().split("\\(")[0].trim());
            List<SQLExpr> arguments = column.getDataType().getArguments();
            if(CollectionUtils.isNotEmpty(arguments)){
                if(arguments.size() == 1 && arguments.get(0) instanceof SQLIntegerExpr){
                    attrs.put(DataModelAttribute.LENGTH, arguments.get(0));
                }
                if(arguments.size() == 2){
                    if(arguments.get(0) instanceof SQLIntegerExpr){
                        attrs.put(DataModelAttribute.LENGTH, arguments.get(0));
                    }
                    if(arguments.get(1) instanceof SQLIntegerExpr){
                        attrs.put(DataModelAttribute.PRECISION, arguments.get(1));
                    }
                }
            }
        }
        if(column.getDefaultExpr() != null && !column.getDefaultExpr().toString().equals(NULL)){
            attrs.put(DataModelAttribute.DEFAULT_VAL, column.getDefaultExpr());
        }
        attrs.put(DataModelAttribute.PRIMARY_KEY, Boolean.toString(false));
        attrs.put(DataModelAttribute.FOREIGN_KEY, Boolean.toString(false));
        attrs.put(DataModelAttribute.NON_EMPTY, Boolean.toString(false));
        for (SQLColumnConstraint constraint : column.getConstraints()) {
            if(constraint instanceof SQLNotNullConstraint){
                attrs.put(DataModelAttribute.NON_EMPTY, Boolean.toString(true));
            }
        }
        if(primaryKeyNames.contains(enName)){
            attrs.put(DataModelAttribute.PRIMARY_KEY, Boolean.toString(true));
        }else{
            attrs.put(DataModelAttribute.PRIMARY_KEY, Boolean.toString(false));
        }
        attrs.put(DataModelAttribute.ENTITY, entityCode);
        attrs.put(DataModelAttribute.INHERIT_ID, Long.toString(ESUtil.getUUID()));
        attribute.setAttrs(attrs);
        return attribute;
    }

    private ESDiagramNode getNewDiagramNode(ESDiagram diagram, String sheetId, CcCiClass entityClass, ESCIInfo entity, List<ESCIInfo> attrs){
        DiagramNodeJson nodeJson = JSON.parseObject(NODE_JSON, DiagramNodeJson.class);
        ESDiagramNode node = new ESDiagramNode();
        node.setId(ESUtil.getUUID());
        node.setVisible(1);
        node.setDiagramId(diagram.getId());
        node.setDEnergy(diagram.getDEnergy());
        node.setSheetId(sheetId);
        node.setKey(UUID.randomUUID().toString());
        nodeJson.setKey(node.getKey());
        nodeJson.setClassId(entityClass.getId());
        nodeJson.setClassCode(entityClass.getClassCode());
        nodeJson.setClassName(entityClass.getClassName());
        nodeJson.setCiPrimaryKey(entity.getCiPrimaryKey());
        nodeJson.setCiId(entity.getId());
        nodeJson.setCiCode(entity.getCiCode());
        nodeJson.setLabel(entity.getCiLabel());
        //TODO 整理实体属性
        node.setNodeJson(JSON.toJSONString(nodeJson));
        return node;
    }
}
